package cn.wolfcode.business.service.impl;

import cn.wolfcode.business.domain.BpmnInfo;
import cn.wolfcode.business.mapper.BpmnInfoMapper;
import cn.wolfcode.business.service.IBpmnInfoService;
import cn.wolfcode.business.vo.DeployVO;
import cn.wolfcode.common.exception.ServiceException;
import cn.wolfcode.common.utils.file.FileUploadUtils;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

/**
 * 流程定义明细Service业务层处理
 *
 * @author dalang
 * @date 2023-11-01
 */
@Service
@Transactional
public class BpmnInfoServiceImpl implements IBpmnInfoService {
    @Autowired
    private BpmnInfoMapper bpmnInfoMapper;

    @Autowired
    private RepositoryService repositoryService;

    /**
     * 查询流程定义明细
     *
     * @param id 流程定义明细主键
     * @return 流程定义明细
     */
    @Override
    public BpmnInfo selectBpmnInfoById(Long id) {
        return bpmnInfoMapper.selectBpmnInfoById(id);
    }

    /**
     * 查询流程定义明细列表
     *
     * @param bpmnInfo 流程定义明细
     * @return 流程定义明细
     */
    @Override
    public List<BpmnInfo> selectBpmnInfoList(BpmnInfo bpmnInfo) {
        return bpmnInfoMapper.selectBpmnInfoList(bpmnInfo);
    }

    /**
     * 新增流程定义明细
     *
     * @param bpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int insertBpmnInfo(BpmnInfo bpmnInfo) {
        return bpmnInfoMapper.insertBpmnInfo(bpmnInfo);
    }

    /**
     * 修改流程定义明细
     *
     * @param bpmnInfo 流程定义明细
     * @return 结果
     */
    @Override
    public int updateBpmnInfo(BpmnInfo bpmnInfo) {
        return bpmnInfoMapper.updateBpmnInfo(bpmnInfo);
    }

    /**
     * 批量撤销流程定义明细
     *
     * @param ids 需要删除的流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBpmnInfoByIds(Long[] ids) {
        if (ids==null||ids.length<1) {
            throw new ServiceException("参数异常");
        }

        for (Long id : ids) {
            BpmnInfo bpmnInfo = bpmnInfoMapper.selectBpmnInfoById(id);
            if (bpmnInfo==null) {
                throw new ServiceException("参数异常");
            }

            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
                    .processDefinitionVersion(bpmnInfo.getVersion())
                    .singleResult();

            if (processDefinition==null) {
                throw new ServiceException("存在撤销项参数异常");
            }

            repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true);

            bpmnInfoMapper.deleteBpmnInfoById(id);
        }
        return 1;
    }

    /**
     * 删除流程定义明细信息
     *
     * @param id 流程定义明细主键
     * @return 结果
     */
    @Override
    public int deleteBpmnInfoById(Long id) {
        return bpmnInfoMapper.deleteBpmnInfoById(id);
    }

    @Override
    public void deploy(DeployVO vo) throws IOException {
        if (vo == null) {
            throw new ServiceException("非法参数");
        }

        MultipartFile file = vo.getFile();

        if (file == null || file.getSize() == 0) {
            throw new ServiceException("必须选择一个流程文件");
        }

        String ext = FileUploadUtils.getExtension(file);
        if (!"bpmn".equalsIgnoreCase(ext)) {
            throw new ServiceException("文件格式必须为 bpmn 格式");
        }

        // 流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addInputStream(vo.getBpmnLabel(), file.getInputStream())
                .deploy();

        // 流程类-解析流程文件
        ProcessDefinition processDefinition = repositoryService
                .createProcessDefinitionQuery()
                .deploymentId(deployment.getId())
                .singleResult();

        BpmnInfo bpmnInfo = new BpmnInfo();
        bpmnInfo.setBpmnLabel(vo.getBpmnLabel());
        bpmnInfo.setBpmnType(vo.getBpmnType());
        bpmnInfo.setProcessDefinitionKey(processDefinition.getKey());
        bpmnInfo.setDeployTime(deployment.getDeploymentTime());
        bpmnInfo.setVersion(processDefinition.getVersion());
        bpmnInfo.setInfo(vo.getInfo());

        bpmnInfoMapper.insertBpmnInfo(bpmnInfo);
    }

    @Override
    public InputStream getResource(String type, Long id) {
        BpmnInfo bpmnInfo = bpmnInfoMapper.selectBpmnInfoById(id);

        if (bpmnInfo==null||!("xml".equalsIgnoreCase(type)||"png".equalsIgnoreCase(type))) {
            throw new ServiceException("参数异常或文件格式异常");
        }

        InputStream inputStream = null;

        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(bpmnInfo.getProcessDefinitionKey())
                .processDefinitionVersion(bpmnInfo.getVersion())
                .singleResult();
        if("xml".equalsIgnoreCase(type)){
            inputStream = repositoryService
                    .getResourceAsStream(processDefinition.getDeploymentId(), bpmnInfo.getBpmnLabel());
        }else if("png".equalsIgnoreCase(type)){
            DefaultProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
            BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
            /**
             * 第一个参数: 流程定义模型
             * 第二个参数: 高亮节点集合
             * 第三个参数: 高亮连线集合
             */
            inputStream = processDiagramGenerator.generateDiagram(bpmnModel,
                    Collections.emptyList(),
                    Collections.emptyList(),
                    "宋体",
                    "宋体",
                    "宋体");
        }
        return inputStream;
    }
}
